﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using EasyBuildingCMS.BLL.BaseEntity;
using System.Data;

namespace EasyBuildingCMS.BLL.CoreEngine
{
    public class PageRepository : CoreEngineBaseRepository
    {
        public PageRepository() {
            CacheKey += "_Page";
        }

        #region Query

        public List<Page> GetAcitvePages()
        {
            string key = CacheKey + "_Active";

            if (EnableCaching && Cache[key] != null)
            {
                return (List<Page>)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;
            
            List<Page> pages = (from page in CoreEngineContext.Pages
                                       where page.Active
                                       orderby page.CreatedDate descending
                                       select page).ToList();

            if (EnableCaching)
            {
                CacheData(key, pages, CacheDuration);
            }

            return pages;
        }

        public List<Page> GetSiteMap()
        {
            string key = CacheKey + "_SiteMap";

            if (EnableCaching && Cache[key] != null)
            {
                return (List<Page>)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;

            List<Page> pages = (from page in CoreEngineContext.Pages
                                //where page.Approved && page.PublishDate <= DateTime.Now && page.ExpireDate > DateTime.Now && page.Active && page.Visible
                                orderby page.SortOrder
                                select page).ToList();

            if (EnableCaching)
            {
                CacheData(key, pages, CacheDuration);
            }

            return pages;
        }

        public List<string> GetCurrentPageNavigationTextPath(int pageID)
        {
            List<string> navigationPath = new List<string>();
            Page currentPage = this.GetPageByID(pageID);
            navigationPath.Add(currentPage.PageNavigationText);
            
            while (currentPage.ParentPageID != null) 
            {
                navigationPath.Insert(0, currentPage.ParentPage.PageNavigationText);
                currentPage = currentPage.ParentPage;
            }

            return navigationPath;

        }

        public List<string> GetCurrentPageNavigationUrlPath(int pageID)
        {
            List<string> navigationPath = new List<string>();
            Page currentPage = this.GetPageByID(pageID);
            navigationPath.Add(currentPage.VirtualHandleName);

            while (currentPage.ParentPageID != null)
            {
                navigationPath.Insert(0, currentPage.ParentPage.VirtualHandleName);
                currentPage = currentPage.ParentPage;
            }

            return navigationPath;

        }

        public List<Page> GetAllPages()
        {
            string key = CacheKey + "_All";

            if (EnableCaching && Cache[key] != null)
            {
                return (List<Page>)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;

            List<Page> pages = (from page in CoreEngineContext.Pages
                                orderby page.CreatedDate descending
                                select page).ToList();

            if (EnableCaching)
            {
                CacheData(key, pages, CacheDuration);
            }

            return pages;
        }

        public List<Page> GetInacitvePages()
        {
            string key = CacheKey + "_Inactive";

            if (EnableCaching && Cache[key] != null)
            {
                return (List<Page>)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;

            List<Page> pages = (from page in CoreEngineContext.Pages
                                where !page.Active
                                orderby page.CreatedDate descending
                                select page).ToList();

            if (EnableCaching)
            {
                CacheData(key, pages, CacheDuration);
            }

            return pages;
        }

        public List<Page> GetPublishedPages()
        {
            string key = CacheKey + "_Published";

            if (EnableCaching && Cache[key] != null)
            {
                return (List<Page>)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;

            List<Page> pages = (from page in CoreEngineContext.Pages
                                where page.Published
                                orderby page.PublishDate descending
                                select page).ToList();

            if (EnableCaching)
            {
                CacheData(key, pages, CacheDuration);
            }

            return pages;
        }

        public List<Page> GetPublishedPages(bool PublishedOnly, int PageIndex, int PageSize)
        {
            string key = String.Format(
                CacheKey + "_{0}_{1}_{2}", PageIndex.ToString(), PageSize.ToString(), PublishedOnly.ToString());

            if (EnableCaching && Cache[key] != null)
            {
                return (List<Page>)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;
            List<Page> pages = null;

            if (PublishedOnly)
            {
                pages = (from page in CoreEngineContext.Pages
                                where page.Published
                                orderby page.PublishDate descending
                                select page).Skip(PageSize * PageIndex).Take(PageSize).ToList();
            }
            else
            {
                pages = (from page in CoreEngineContext.Pages
                         where page.Published
                         orderby page.PublishDate descending
                         select page).Skip(PageSize * PageIndex).Take(PageSize).ToList();
            }

            if (EnableCaching)
            {
                CacheData(key, pages, CacheDuration);
            }

            return pages;
        }

        public IEnumerable<Page> GetEnumerablePageList()
        {

            string key = CacheKey + "_IEnumerable";

            if (EnableCaching && (Cache[key] != null))
            {
                return (IEnumerable<Page>)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;
            IEnumerable<Page> pages = (from page in CoreEngineContext.Pages
                                       where page.Active
                                       orderby page.CreatedDate descending
                                       select page).AsEnumerable<Page>();

            if (EnableCaching)
            {
                CacheData(key, pages, CacheDuration);
            }

            return pages;
        }

        public Page GetPageByID(int pageID)
        {

            string key = string.Format(CacheKey + "_page_{0}", pageID);

            if (EnableCaching && (Cache[key] != null))
            {
                return (Page)Cache[key];
            }

            //this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;
            Page page = this.CoreEngineContext.Pages.Where(p => p.PageID == pageID).FirstOrDefault<Page>();

            if (EnableCaching)
            {
                CacheData(key, page, CacheDuration);
            }

            return page;
        }

        public Page GetPageByUrl(string url)
        {
            string key = string.Format(CacheKey + "_page_{0}", url);

            if (EnableCaching && (Cache[key] != null))
            {
                return (Page)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;
            Page page = this.CoreEngineContext.Pages.Where(p => p.VirtualHandleName == url).FirstOrDefault<Page>();

            if (EnableCaching)
            {
                CacheData(key, page, CacheDuration);
            }

            return page;
        }

        public Page GetHomePage()
        {
            string key = CacheKey + "_homepage";

            if (EnableCaching && (Cache[key] != null))
            {
                return (Page)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;
            Page page = this.CoreEngineContext.Pages.Where(p => p.HomePage == true).FirstOrDefault<Page>();

            if (EnableCaching)
            {
                CacheData(key, page, CacheDuration);
            }

            return page;
        }

        public DataTable GetPageDateTable() {
            string key = CacheKey + "_PageDateTable";

            if (EnableCaching && (Cache[key] != null))
            {
                return (DataTable)Cache[key];
            }

            this.CoreEngineContext.Pages.MergeOption = MergeOption.NoTracking;

            List<Page> pages = (from page in CoreEngineContext.Pages
                                where page.Active
                                orderby page.SortOrder
                                select page).ToList();

            DataTable dataTable = new DataTable();
            dataTable.Columns.Add(new DataColumn("PageID", typeof(int)));
            dataTable.Columns.Add(new DataColumn("ParentPageID", typeof(int)));
            dataTable.Columns.Add(new DataColumn("VirtualHandleName", typeof(string)));
            dataTable.Columns.Add(new DataColumn("PageNavigationText", typeof(string)));

            foreach (Page page in pages) 
            {
                dataTable.Rows.Add(page.PageID, page.ParentPageID, page.VirtualHandleName, page.PageNavigationText);
            }

            if (EnableCaching)
            {
                CacheData(key, dataTable, CacheDuration);
            }

            return dataTable;
        }

        #endregion

        #region Update

     

        public bool UpdateHomePage(int pageID)
        {
            List<Page> pages = (from page in CoreEngineContext.Pages
                                where page.HomePage == true
                                select page).ToList();

            foreach (Page page in pages)
            {
                page.HomePage = false;
            }

            Page homePage = this.GetPageByID(pageID);
            homePage.HomePage = true;

            return base.SaveChange(pageID);
        }

        public bool UpdatePageVisibility(int pageID, Boolean visiable)
        {
            Page page = this.GetPageByID(pageID);
            page.Active = visiable;

            return base.SaveChange(pageID);
        }

        public bool UpdatePublishDate(int pageID, DateTime publishDate)
        {
            Page page = this.GetPageByID(pageID);
            page.PublishDate = publishDate;

            return base.SaveChange(pageID);
        }

        public bool UpdateExpireDate(int pageID, DateTime expireDate)
        {
            Page page = this.GetPageByID(pageID);
            page.ExpireDate = expireDate;

            return base.SaveChange(pageID);
        }

        public bool UpdateLastRevision(int pageID, string userName, DateTime revisionDate)
        {
            Page page = this.GetPageByID(pageID);
            page.LastRevisionUserName = userName;
            page.LastRevisonDate = revisionDate;

            return base.SaveChange(pageID);
        }

        public bool UpdateApproval(int pageID, bool approved, string approvedBy, DateTime approveDate)
        {
            Page page = this.GetPageByID(pageID);
            page.Approved = approved;
            page.ApprovedBy = approvedBy;
            page.ApprovedDate = approveDate;

            return base.SaveChange(pageID);
        }

        public bool UpdatePageNavigationText(int pageID, string navigationText)
        {
            Page page = this.GetPageByID(pageID);
            page.PageNavigationText = navigationText;

            return base.SaveChange(pageID);
        }

        public bool UpdateParentNode(int pageID, int? parentPageID) {

            Page page = this.GetPageByID(pageID);
            page.ParentPageID = parentPageID;
            return base.SaveChange(pageID);
        }

        public bool UpdateSortOrder(int pageID, int sortOrder)
        {
            Page page = this.GetPageByID(pageID);
            page.SortOrder = sortOrder;
            return base.SaveChange(pageID);
        }

        public bool UpdatePage(int pageID, string virtualHandleName, string pageTile, string pageDescription, string pageNavigationText,
            int? masterPageID, string internalRedirectionUrl, string externalRedirectionUrl, string pageMetaDescription, string pageMetaKeyword,
            bool approved, DateTime? publishedDate, DateTime? expireDate, int sortOrder, string cssClass, bool visiable)
        {
            Page page = this.GetPageByID(pageID);
            page.VirtualHandleName = Helper.FormatSpacesForURL(virtualHandleName);
            page.PageTitle = pageTile;
            page.PageDescription = pageDescription;
            page.MasterPageID = masterPageID;
            page.InternalRedirectionURL = internalRedirectionUrl;
            page.ExternalRedirectionURL = externalRedirectionUrl;
            page.PageMetaDescription = pageMetaDescription;
            page.PageMetaKeywords = pageMetaKeyword;
            page.LastRevisionUserName = Helper.CurrentUserName;
            page.LastRevisonDate = DateTime.Now;
            page.PublishDate = publishedDate;
            page.ExpireDate = expireDate;
            page.SortOrder = sortOrder;
            page.CssClass = cssClass;
            page.Visible = visiable;
            page.Approved = approved;
            if (page.Approved != approved){
                if (approved)
                {
                    page.ApprovedBy = Helper.CurrentUserName;
                    page.ApprovedDate = DateTime.Now;
                }
                else
                {
                    page.ApprovedBy = null;
                    page.ApprovedDate = null;
                }
            }

            return base.SaveChange(pageID);
        
        }

        #endregion

        #region Insert

        public Page InsertPage(int pageID, int? parentPageID, string virtualHandleName, string pageTile, string pageDescription, string pageNavigationText,
            int? masterPageID, string internalRedirectionUrl, string externalRedirectionUrl, string pageMetaDescription, string pageMetaKeyword,
            bool approved, DateTime? publishedDate, DateTime? expireDate, int sortOrder, string cssClass, bool visiable) 
        { 
        
            Page page = Page.CreatePage(pageID, pageNavigationText, approved, visiable, true);
            page.ParentPageID = parentPageID;
            page.VirtualHandleName = Helper.FormatSpacesForURL(virtualHandleName);
            page.PageTitle = pageTile;
            page.PageDescription = pageDescription;
            page.MasterPageID = masterPageID;
            page.InternalRedirectionURL = internalRedirectionUrl;
            page.ExternalRedirectionURL = externalRedirectionUrl;
            page.PageMetaDescription = pageMetaDescription;
            page.PageMetaKeywords = pageMetaKeyword;
            page.CreatedBy = Helper.CurrentUserName;
            page.CreatedDate = DateTime.Now;
            page.Approved = approved;
            if (approved)
            {
                page.ApprovedBy = Helper.CurrentUserName;
                page.ApprovedDate = DateTime.Now;
            }
            else {
                page.ApprovedBy = null;
                page.ApprovedDate = null;
            }
            page.PublishDate = publishedDate;
            page.ExpireDate = expireDate;
            page.SortOrder = sortOrder;
            page.CssClass = cssClass;
            page.Visible = visiable;

           return this.InsertPage(page);
        
        }
   
        public Page InsertPage(Page page)
        {

            try
            {
                if (page.EntityState == EntityState.Detached)
                {
                    this.CoreEngineContext.AddToPages(page);
                }
                if (base.SaveChange(page.PageID)){
                    return page;
                }
                else{
                    return null;
                }
            }
            catch (Exception ex)
            {
                ActiveExceptions.Add(CacheKey + "_" + page.PageID, ex);
                return null;

            }
        }

        #endregion
      
        #region " Delete Operations "

        public bool DeletePage(int pageId)
        {
            return ChangeDeletedState(this.GetPageByID(pageId), false);
        }

        public bool DeletePage(Page page)
        {
            return ChangeDeletedState(page, false);
        }

        public bool UnDeletePage(Page page)
        {
            return ChangeDeletedState(page, true);
        }

        private bool ChangeDeletedState(Page page, bool state)
        {
            page.Active = state;
            return base.SaveChange(page.PageID);
        }

        #endregion

    }
}
